﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Windows.Forms;
using System.Drawing;
using System.Drawing.Drawing2D;

namespace uz.control
{
    public class UzTreeNode
    {
        #region 构造函数
        /// <summary>
        /// 构造函数
        /// </summary>
        public UzTreeNode()
        {
            ToolBar = new UzTreeNodeToolBar(this);
            ToolBar.RunCommand += new UzTreeNodeToolBar.HandleRunCommand(ToolBar_RunCommand);
        }

        void ToolBar_RunCommand(string CommandName)
        {
            RunCommand(CommandName);
        }

        public const string CMD_ADD_STR = "add";
        public const string CMD_DEL_STR = "del";
        public const string CMD_EDIT_STR = "upd";
        public const string CMD_ADD_CHILD_STR = "addChild";

        public virtual void RunCommand(string cmdName)
        {
            if (cmdName == CMD_ADD_STR)
            {
                Add();
            }
            else if (cmdName == CMD_DEL_STR)
            {
                Delete();
            }
            else if (cmdName == CMD_EDIT_STR)
            {
                Edit();
            }
            else if (cmdName == CMD_ADD_CHILD_STR)
            {
                AddChild();
            }
        }
        public virtual void Edit()
        {
            IsEdit = true;
        }

        public virtual void Add()
        {
            if (Parent != null)
            {
                Parent.AddChild();
            }
        }

        public virtual void Delete()
        {
        }
        #endregion
        
        private string _ID = "";

        public virtual string ID
        {
            get { return _ID; }
            set { _ID = value; }
        }
        private string _Name = "";

        public virtual string Name
        {
            get { return _Name; }
            set { _Name = value; }
        }
    
        #region 父节点：Parent
        /// <summary>
        /// 父节点
        /// </summary>
        private UzTreeNode _Parent = null;
        /// <summary>
        /// 父节点
        /// </summary>
        public UzTreeNode Parent
        {
            get { return _Parent; }
            set { _Parent = value; }
        }
        #endregion

        #region 节点的容器控件：UzTreeView
        /// <summary>
        /// 节点的容器控件
        /// </summary>
        private UzTreeView _UzTreeView = null;
        /// <summary>
        /// 节点的容器控件
        /// </summary>
        public UzTreeView UzTreeView
        {
            set
            {
                _UzTreeView = value;
            }
            get 
            {
                if (Parent == null)
                {
                    return _UzTreeView;
                }
                else
                {
                    return Parent.UzTreeView;
                }
            }
        }
        #endregion

        #region 子节点集合:Nodes
        /// <summary>
        /// 子节点集合
        /// </summary>
        private UzTreeNodeCollection _Nodes = null;
        /// <summary>
        /// 子节点集合
        /// </summary>
        public UzTreeNodeCollection Nodes
        {
            get
            {

                if (_Nodes == null)
                {
                    _Nodes = new UzTreeNodeCollection() { Parent = this};
                }
                return _Nodes;
            }
        }
        #endregion

        #region 节点是否可见：IsVisible
        /// <summary>
        /// 节点是否可见
        /// </summary>
        private bool _IsVisible = true;
        /// <summary>
        /// 节点是否可见
        /// </summary>
        public virtual bool IsVisible
        {
            get { return _IsVisible; }
            set 
            { 
                _IsVisible = value;
                if (value == true)
                {
                    Show();
                }
                else
                {
                    Hide();
                }
            }
        }
        #endregion

        #region 节点是否展开：IsExpanded
        /// <summary>
        /// 节点是否展开
        /// </summary>
        private bool _IsExpanded = true;
        /// <summary>
        /// 节点是否展开
        /// </summary>
        public bool IsExpanded
        {
            get { return _IsExpanded; }
        }
        #endregion

        #region 当前节点是否被选择：IsSelected
        /// <summary>
        /// 当前节点是否被选择
        /// </summary>
        private bool _IsSelected = false;
        /// <summary>
        /// 当前节点是否被选择
        /// </summary>
        public bool IsSelected
        {
            get { return _IsSelected; }
            set
            {
                if (IsEdit == true && value == false)
                {
                    IsEdit = false;
                }
                _IsSelected = value;

            }
        }
        #endregion

        #region 节点高度：Hegiht
        /// <summary>
        /// 节点高度，默认未UzTreeView的ItemHeight
        /// </summary>
        private int _Height = -1;
        /// <summary>
        /// 节点高度，默认未UzTreeView的ItemHeight
        /// </summary>
        public virtual int Height
        {
            get
            {
                if (_Height == -1)
                {
                    _Height = UzTreeView.ItemHeight;
                }
                return _Height;
            }
            set
            {
                _Height = value;
            }
        }
        #endregion

        #region 在子节点集合中的索引：Index
        /// <summary>
        /// 在子节点集合中的索引
        /// </summary>
        private int _Index = -1;
        /// <summary>
        /// 在子节点集合中的索引
        /// </summary>
        public int Index
        {
            get { return _Index; }
            set { _Index = value; }
        }
        #endregion

        #region 子节点缩进宽度：Indent
        /// <summary>
        /// 子节点缩进宽度
        /// </summary>
        private int _Indent = -1;
        /// <summary>
        /// 子节点缩进宽度
        /// </summary>
        public int Indent
        {
            get
            {
                if (_Indent == -1)
                {
                    _Indent = UzTreeView.Indent;
                }
                return _Indent;
            }
            set { _Indent = value; }
        }

        /// <summary>
        /// 获取当前节点的缩进宽度
        /// </summary>
        /// <returns>缩进宽度</returns>
        public int GetIndentWidth()
        {
            return Leave * Indent;
        }

        #endregion

        #region 操作手柄区域宽度：HandleAreaWidth
        /// <summary>
        /// 操作手柄区域宽度
        /// </summary>
        private int _HandleAreaWidth = -1;
        /// <summary>
        /// 操作手柄区域宽度
        /// </summary>
        public virtual int HandleAreaWidth
        {
            get
            {
                if (_HandleAreaWidth == -1)
                {
                    _HandleAreaWidth = UzTreeView.HandleAreaWidth;
                }
                return _HandleAreaWidth;
            }
            set { _HandleAreaWidth = value; }
        }
        #endregion

        #region 命令工具栏对象：ToolBar
        /// <summary>
        /// 命令工具栏对象
        /// </summary>
        public UzTreeNodeToolBar ToolBar { get; set; }
        #endregion

        #region 节点是否处于编辑状态：IsEdit
        /// <summary>
        /// 节点是否处于编辑状态
        /// </summary>
        private bool _IsEdit = false;
        /// <summary>
        /// 节点是否处于编辑状态
        /// </summary>
        public virtual bool IsEdit
        {
            get { return _IsEdit; }
            set 
            { 
                _IsEdit = value;
            }
        }
        #endregion

        #region 根节点：RootNode
        /// <summary>
        /// 根节点
        /// </summary>
        public UzTreeNode RootNode
        {
            get
            {
                UzTreeNode node = this;

                while (node.Parent != null)
                {
                    node = node.Parent;
                }

                return node;
            }

        }

        #endregion

        #region 节点绘制：Paint，DrawNode，DrawLeftLine，DrawNodeContent，DrawNodeText，DrawNodeBackGround，DrawHandle
        /// <summary>
        /// 绘制方法
        /// </summary>
        /// <param name="e">绘制事件参数</param>
        internal void Paint(PaintEventArgs e,Rectangle ViewBounds,Rectangle NodeBounds)
        {
            if (NodeBounds.Top > ViewBounds.Bottom + NodeBounds.Height)
            {
                return;
            }

            if (IsVisible == true)
            {
                DrawNode(e, ViewBounds, NodeBounds);

                UzTreeNode node = GetNextVisibleNode();

                if (node != null)
                {
                    Rectangle rect = new Rectangle(
                        0,
                        NodeBounds.Bottom,
                        ViewBounds.Width,
                        node.Height
                    );
                    node.Paint(e, ViewBounds, rect);
                }
                else
                {
                    e.Graphics.DrawLine(
                        Pens.Black,
                        0,
                        NodeBounds.Bottom,
                        ViewBounds.Width,
                        NodeBounds.Bottom
                    );

                }
            }
        }

        /// <summary>
        /// 绘制节点
        /// </summary>
        /// <param name="e">绘制事件参数</param>
        public virtual void DrawNode(PaintEventArgs e,Rectangle ViewBounds,Rectangle NodeBounds)
        {
            //节点画刷
            Brush BackBrush = new SolidBrush(UzTreeView.BackColor);
            Brush ForeBrush = new SolidBrush(UzTreeView.ForeColor);
            Brush SelectedBackBrush = new SolidBrush(UzTreeView.NodeSelectedBackColor);
            Brush SelectedForeBrush = new SolidBrush(UzTreeView.NodeSelectedForeColor);

            //节点边框的画笔
            Pen BorderPen = new Pen(UzTreeView.NodeBorderColor);

            //绘制节点内容
            DrawNodeContent(e, BackBrush, ForeBrush, SelectedBackBrush, SelectedForeBrush, NodeBounds);

            //绘制节点的边框
            e.Graphics.DrawLine(BorderPen, NodeBounds.Left + GetIndentWidth(), NodeBounds.Top, NodeBounds.Right, NodeBounds.Top);

            //绘制节点父的左边线
            DrawLeftLine(e, BorderPen, NodeBounds);

            //绘制节点控制区域
            DrawHandle(e, NodeBounds);

            //绘制命令工具栏
            if (IsSelected == true && IsEdit == false)
            {
                ToolBar.DrawToolBar(e, NodeBounds, UzTreeView.Font);
            }

            BackBrush.Dispose();
            ForeBrush.Dispose();
            SelectedBackBrush.Dispose();
            SelectedForeBrush.Dispose();
            BorderPen.Dispose();
        }

        /// <summary>
        /// 绘制节点左边线
        /// </summary>
        /// <param name="e">绘制事件参数</param>
        /// <param name="BorderPen">边框画笔</param>
        /// <param name="Bounds">节点区域</param>
        public virtual void DrawLeftLine(PaintEventArgs e, Pen BorderPen, Rectangle Bounds)
        {
            //UzTreeNode node = this;
            //while (node != null)
            //{
            //    int w = node.GetIndentWidth();
            //    e.Graphics.DrawLine(
            //        BorderPen,
            //        w,
            //        Bounds.Top,
            //        w,
            //        Bounds.Top + Height
            //    );

            //    node = node.Parent;
            //}

            int c = Leave;
            int w = 0;
            for (int i = 0; i < c; i++)
            {
                w += Indent;
                e.Graphics.DrawLine(
                    BorderPen,
                    w,
                    Bounds.Top,
                    w,
                    Bounds.Top + Height
                );
            }
        }

        /// <summary>
        /// 绘制节点内容
        /// </summary>
        /// <param name="e">绘制事件参数</param>
        /// <param name="BackBrush">背景画刷</param>
        /// <param name="ForeBrush">前景画刷</param>
        /// <param name="SelectedBackBrush">选择时背景画刷</param>
        /// <param name="SelectedForeBrush">选择是前景画刷</param>
        /// <param name="Bounds">节点区域</param>
        public virtual void DrawNodeContent(PaintEventArgs e, Brush BackBrush, Brush ForeBrush, Brush SelectedBackBrush, Brush SelectedForeBrush, Rectangle Bounds)
        {
            if (IsSelected == true)
            {
                DrawNodeBackGround(e, SelectedBackBrush, Bounds);
                DrawNodeText(e, SelectedForeBrush, Bounds);
            }
            else
            {
                DrawNodeBackGround(e, BackBrush, Bounds);
                DrawNodeText(e, ForeBrush, Bounds);
            }
        }

        /// <summary>
        /// 绘制节点的文本
        /// </summary>
        /// <param name="e">绘制事件参数</param>
        /// <param name="brush">前景画刷</param>
        /// <param name="Bounds">节点区域</param>
        public virtual void DrawNodeText(PaintEventArgs e, Brush brush, Rectangle Bounds)
        {
            e.Graphics.DrawString(
                Index.ToString(), 
                UzTreeView.Font, 
                brush, 
                Bounds.Left + HandleAreaWidth + GetIndentWidth(), 
                Bounds.Top
            );
        }

        /// <summary>
        /// 绘制节点的背景
        /// </summary>
        /// <param name="e">绘制事件参数</param>
        /// <param name="BackBrush">背景画刷</param>
        /// <param name="Bounds">背景取悦</param>
        public virtual void DrawNodeBackGround(PaintEventArgs e, Brush BackBrush, Rectangle Bounds)
        {
            e.Graphics.FillRectangle(
                BackBrush, 
                Bounds.Left + GetIndentWidth(),
                Bounds.Top,
                Bounds.Width,
                Bounds.Height
            );
        }

        /// <summary>
        /// 绘制节点的操作区域
        /// </summary>
        /// <param name="e">绘制事件参数</param>
        public virtual void DrawHandle(PaintEventArgs e,Rectangle Bounds)
        {
            Rectangle rect = GetHandleRect(Bounds);

            e.Graphics.SmoothingMode = SmoothingMode.HighQuality;

            if (IsSelected == true)
            {
                if (IsEdit == true)
                {
                    e.Graphics.FillEllipse(Brushes.Tomato, rect);
                }
                else
                {
                    e.Graphics.FillEllipse(Brushes.SkyBlue, rect);
                }
            }
            else
            {
                e.Graphics.FillEllipse(Brushes.GreenYellow, rect);
            }

            e.Graphics.DrawArc(Pens.Blue, rect, 0, 360);


            if (Nodes.Count == 0)
            {
                return;
            }

            e.Graphics.DrawLine(
                Pens.Blue,
                rect.Left,
                rect.Top+ rect.Height/2,
                rect.Right,
                rect.Top+ rect.Height/2
            );
            if (IsExpanded == false)
            {
                e.Graphics.DrawLine(
                    Pens.Blue,
                    rect.Left + rect.Width/2,
                    rect.Top,
                    rect.Left + rect.Width/2,
                    rect.Bottom
                );    
            }

            e.Graphics.SmoothingMode = SmoothingMode.None;
        }
        #endregion

        public int Leave
        {
            get
            {
                if (Parent == null)
                {
                    return 0;
                }
                else
                {
                    return Parent.Leave + 1;
                }
            }
        }

        #region 获得节点的控制点区域：GetHandleRect
        /// <summary>
        /// 获得节点的控制点区域
        /// </summary>
        /// <param name="Bounds">节点区域</param>
        /// <returns>控制点区域</returns>
        public virtual Rectangle GetHandleRect(Rectangle Bounds)
        {
            int h = Math.Min(Math.Min(Height, HandleAreaWidth), 12);
            int x = Bounds.X + GetIndentWidth();
            int y = Bounds.Y;

            return new Rectangle(
                x + Math.Max(0,(HandleAreaWidth - h) /2 ), 
                y + Math.Max(0,(Height-h)/2), 
                h, 
                h
            );
        }
        #endregion

        #region 节点导航
        /// <summary>
        /// 获得下一个可见节点
        /// </summary>
        /// <returns>下一个可见节点</returns>
        public UzTreeNode GetNextVisibleNode()
        {
            UzTreeNode node = GetNextNode();

            while (node != null)
            {
                if (node.IsVisible == true)
                {
                    return node;
                }

                node = node.GetNextNode();
            }

            return null;
        }
        /// <summary>
        /// 获得上一个可见节点
        /// </summary>
        /// <returns>上一个可见节点</returns>
        public UzTreeNode GetPrevVisibleNode()
        {
            UzTreeNode node = GetPrevNode();

            while (node != null)
            {
                if (node.IsVisible == true)
                {
                    return node;
                }

                node = node.GetPrevNode();
            }

            return null;
        }

        /// <summary>
        /// 获得下一个节点
        /// </summary>
        /// <returns>下一个节点，没有返回Null</returns>
        public UzTreeNode GetNextNode()
        {
            if (FirstNode != null)
            {
                return FirstNode;
            }

            UzTreeNode node = this;

            while (node != null)
            {
                if (node.GetNextBrotherNode() != null)
                {
                    return node.GetNextBrotherNode();
                }

                node = node.Parent;
            }

            return null;

        }

        /// <summary>
        /// 获得上一个节点
        /// </summary>
        /// <returns></returns>
        public UzTreeNode GetPrevNode()
        {
            UzTreeNode node = GetPrevBrotherNode();
            UzTreeNode rstNode = node;

            if (Parent == null)
            {
                if (node == null)
                {
                    return null;
                }
                else
                {
                    rstNode = node;
                    while (node != null)
                    {
                        rstNode = node;
                        node = node.LastNode;
                    }

                    return rstNode;
                }
            }
            else
            {
                if (node == null)
                {
                    rstNode = Parent;
                    while (node != null)
                    {
                        rstNode = node;
                        node = node.LastNode;
                    }

                    return rstNode;

                }
                else
                {
                    while (node != null)
                    {
                        rstNode = node;
                        node = node.LastNode;
                    }

                    return rstNode;
                }
            }

        }

        /// <summary>
        /// 获得当前节点的下一个兄弟节点
        /// </summary>
        /// <returns>下一个兄弟节点，没有返回null</returns>
        public UzTreeNode GetNextBrotherNode()
        {
            if (Parent == null)
            {
                if (UzTreeView.Nodes.Count > Index + 1)
                {
                    return UzTreeView.Nodes[Index + 1];
                }
                else
                {
                    return null;
                }
            }
            else
            {
                if (Parent.Nodes.Count > Index + 1)
                {
                    return Parent.Nodes[Index + 1];
                }
                else
                {
                    return null;
                }
            }
        }

        /// <summary>
        /// 获得当前节点的上一个兄弟节点
        /// </summary>
        /// <returns>上一个兄弟节点，没有返回null</returns>
        public UzTreeNode GetPrevBrotherNode()
        {
            if (Parent == null)
            {
                if (Index > 0)
                {
                    return UzTreeView.Nodes[Index - 1];
                }
                else
                {
                    return null;
                }
            }
            else
            {
                if (Index > 0)
                {
                    return Parent.Nodes[Index - 1];
                }
                else
                {
                    return null;
                }
            }
        }

        private UzTreeNode FirstNode
        {
            get
            {
                if (Nodes.Count == 0)
                {
                    return null;
                }

                return Nodes[0];
            }
        }

        private UzTreeNode LastNode
        {
            get
            {
                if (Nodes.Count == 0)
                {
                    return null;
                }

                return Nodes[Nodes.Count - 1];
            }
        }
        #endregion

        #region 鼠标及键盘事件处理
        /// <summary>
        /// 处理MouseDown
        /// </summary>
        /// <param name="e">事件参数</param>
        /// <returns>处理过返回True，否则返回false</returns>
        public virtual bool ProcessMouseDown(MouseEventArgs e)
        {
            int mode = HitTest(e.Location);
            bool rst = false;

            if (mode == 0)
            {
                if (IsExpanded == true)
                {
                    Collapse();
                }
                else
                {
                    Expand();
                }
            }
            if (mode == 1)
            {
                if (IsSelected == true)
                {
                    rst = ToolBar.RunCommandAtPoint();
                }

                if (rst == false)
                {
                    UzTreeView.SelectedNode = this;
                }
            }

            return rst;
        }

        /// <summary>
        /// 处理MouseMove
        /// </summary>
        /// <param name="e">事件参数</param>
        /// <returns>处理过返回True，否则返回false</returns>
        public virtual bool ProcessMouseMove(MouseEventArgs e)
        {
            int mode = HitTest(e.Location);

            return false;
        }

        /// <summary>
        /// 处理MouseUp
        /// </summary>
        /// <param name="e">事件参数</param>
        /// <returns>处理过返回True，否则返回false</returns>
        public virtual bool ProcessMouseUp(MouseEventArgs e)
        {
            return false;
        }

        /// <summary>
        /// 处理KeyDown
        /// </summary>
        /// <param name="e">事件参数</param>
        /// <returns>处理过返回True，否则返回false</returns>
        public virtual bool ProcessKeyDown(KeyEventArgs e)
        {
            if (e.KeyCode == Keys.F2)
            {
                Edit();
                return true;
            }
            else if (e.KeyCode == Keys.F3)
            {
                Delete();
                return true;
            }
            else if (e.KeyCode == Keys.F4)
            {
                Add();
                return true;
            }
            else if (e.KeyCode == Keys.F5)
            {
                AddChild();
                return true;
            }
            return false;
        }

        /// <summary>
        /// 处理KeyUp
        /// </summary>
        /// <param name="e">事件参数</param>
        /// <returns>处理过返回True，否则返回false</returns>
        public virtual bool ProcessKeyUp(KeyEventArgs e)
        {
            return false;
        }

        /// <summary>
        /// 击中测试
        /// </summary>
        /// <param name="pt">坐标点</param>
        /// <returns>击中的模式</returns>
        public int HitTest(Point pt)
        {
            int w = GetIndentWidth();
            if (pt.X <= w)
            {
                return -1;
            }

            if (pt.X <= w + HandleAreaWidth)
            {
                return 0;
            }

            return 1;
        }
        #endregion

        /// <summary>
        /// 合并节点
        /// </summary>
        public void Collapse()
        {
            foreach (UzTreeNode itm in Nodes)
            {
                itm.IsVisible = false;
                itm.Collapse();
            }

            _IsExpanded = false;
        }

        /// <summary>
        /// 折叠节点
        /// </summary>
        public void Expand()
        {
            foreach (UzTreeNode itm in Nodes)
            {
                itm.IsVisible = true;
            }

            _IsExpanded = true;
        }


        public virtual void Hide()
        {
            if (IsEdit == true)
            {
                IsEdit = false;
            }
        }

        public virtual void Show()
        {

        }

        public virtual UzTreeNode AddChild()
        {
            return null;
        }
    }
}
